1   /*
2    * Copyright (C) 2011 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.util.concurrent;
18  
19  import com.google.caliper.BeforeExperiment;
20  import com.google.caliper.Benchmark;
21  import com.google.caliper.Param;
22  
23  import java.util.concurrent.locks.Lock;
24  import java.util.concurrent.locks.ReentrantLock;
25  
26  /**
27   * Benchmarks for {@link CycleDetectingLockFactory}.
28   *
29   * @author Darick Tong
30   */
31  public class CycleDetectingLockFactoryBenchmark {
32  
33    @Param({"2","3","4","5","10"}) int lockNestingDepth;
34  
35    CycleDetectingLockFactory factory;
36    private Lock[] plainLocks;
37    private Lock[] detectingLocks;
38  
39    @BeforeExperiment
40    void setUp() throws Exception {
41      this.factory = CycleDetectingLockFactory.newInstance(
42          CycleDetectingLockFactory.Policies.WARN);
43      this.plainLocks = new Lock[lockNestingDepth];
44      for (int i = 0; i < lockNestingDepth; i++) {
45        plainLocks[i] = new ReentrantLock();
46      }
47      this.detectingLocks = new Lock[lockNestingDepth];
48      for (int i = 0; i < lockNestingDepth; i++) {
49        detectingLocks[i] = factory.newReentrantLock("Lock" + i);
50      }
51    }
52  
53    @Benchmark void unorderedPlainLocks(int reps) {
54      lockAndUnlock(new ReentrantLock(), reps);
55    }
56  
57    @Benchmark void unorderedCycleDetectingLocks(int reps) {
58      lockAndUnlock(factory.newReentrantLock("foo"), reps);
59    }
60  
61    private void lockAndUnlock(Lock lock, int reps) {
62      for (int i = 0; i < reps; i++) {
63        lock.lock();
64        lock.unlock();
65      }
66    }
67  
68    @Benchmark void orderedPlainLocks(int reps) {
69      lockAndUnlockNested(plainLocks, reps);
70    }
71  
72    @Benchmark void orderedCycleDetectingLocks(int reps) {
73      lockAndUnlockNested(detectingLocks, reps);
74    }
75  
76    private void lockAndUnlockNested(Lock[] locks, int reps) {
77      for (int i = 0; i < reps; i++) {
78        for (int j = 0; j < locks.length; j++) {
79          locks[j].lock();
80        }
81        for (int j = locks.length - 1; j >= 0; j--) {
82          locks[j].unlock();
83        }
84      }
85    }
86  }